/*
 * @Author: xxx
 * @Date: 2024-07-10 15:07:34
 * @LastEditors: xxx
 * @LastEditTime: 2024-07-11 16:13:18
 * @FilePath: \postgresqltest\geometry\geometry3.go
 * @Description: 正式版
 */
package geometry

import (
	"context"
	"fmt"
	"unsafe"

	"github.com/twpayne/go-geom"
	"github.com/twpayne/go-geom/encoding/geojson"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type geomeT struct {
	geom.T
}

type geometryPtr struct {
	uintptr
}

type GeometryV2[T any, K geom.T] struct {
	geom.T
	Data *T
}

func NewGeometryV2[T any, K geom.T](g T, k K) *GeometryV2[T, K] {
	return &GeometryV2[T, K]{
		Data: &g,
	}
}

func (g *GeometryV2[T, K]) Scan(src any) error {
	var t T
	g.Data = &t
	return scan(g.Data, src)
}

func (g *GeometryV2[T, K]) GormValue(ctx context.Context, db *gorm.DB) (expr clause.Expr) {
	return gormValue(g.Data, db)
}

func (g *GeometryV2[T, K]) GormDataType() string {
	return "geometry"
}

func (g *GeometryV2[T, K]) MarshalJSON() ([]byte, error) {
	p := (*geomeT)(unsafe.Pointer(g.Data)).T
	return geojson.Marshal(p)
}

func (g *GeometryV2[T, K]) UnmarshalJSON(data []byte) error {
	err := geojson.Unmarshal(data, &g.T)
	if err != nil {
		return err
	}
	kv, ok := g.T.(K)
	if !ok {
		return fmt.Errorf("rdb: want K, got geom.T")
	}
	var t T
	g.Data = &t
	*(*K)(unsafe.Pointer((&(*geometryPtr)(unsafe.Pointer(g.Data)).uintptr))) = kv
	return nil
}
